package view;

import common.Constant;
import common.Singleton;
import components.MButton;
import components.MDialog;
import operator.Handler;
import platform.AttrOption;
import pri.swg.Dragger;
import pri.swg.Fader;
import pri.swg.LineAZer;
import pri.swg.Slider;
import resource.Resource;
import vo.Attr;
import vo.Mean;

import javax.swing.*;
import javax.swing.border.AbstractBorder;
import javax.swing.border.MatteBorder;
import javax.swing.plaf.ColorUIResource;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.RoundRectangle2D;
import java.util.ArrayList;
import java.util.Iterator;

/**
 *
 * 主界面，负责视图规划<br/>
 *
 * @author 柴家琪
 */
@SuppressWarnings("serial")
public class Main extends JFrame {
    public static Main main;

    private int FHeight = Constant.FHeight, FWidth = Constant.FWidth;
    private Color titleColor = Constant.titleColor;

    private final int MaxSize = 50, MinSize = 20;
    final int defaultAttrWidth = 200;

    public int presentFontSize = 22, recordFontSize = 22, presentPage, recordPage, recordCarePosition,
            recordAttrShowerLoc = FHeight - 196;

    private JTextField jtfCurrentPage = new JTextField("全文");
    private Resource resource = Singleton.resource();
    private MLabel bSizeUp = new MLabel(pngIcon("size_up"), Color.DARK_GRAY),
            bSizeDown = new MLabel(pngIcon("size_down"), Color.DARK_GRAY),
            lPreSize = new MLabel("" + presentFontSize),
            bSave = new MLabel(pngIcon("xdoc_saved"), "已保存", Color.DARK_GRAY),
            bOpenMenu = new MLabel("  ↓", new Color(70, 70, 255)),
            bMinimize = new MLabel("－", new Color(70, 255, 70)),
            bExit = new MLabel("Χ", new Color(255, 70, 70)),
            bLastPara = new MLabel("<", Color.magenta),
            bNextPara = new MLabel(">", Color.MAGENTA),
            bModifyText = new MLabel(pngIcon("adjust"), "编辑文章", Color.DARK_GRAY);
//            bCancelModify = new MLabel(pngIcon("no"), "取消编辑", Color.DARK_GRAY)
    private Fader textModeFader;// 修改模式、隠式模式下

    private JPanel ui, title;
    private GridBagConstraints titleConstraints = new GridBagConstraints();
    private JLayeredPane layeredPane;
    private JTextPane textPane;
    public JPanel rightPanel, textOpsMenu, meanOpsMenu, locSelector, info, hider, confirmer, occupier, normalAttr, attrSetter;
    private LineAZer colors_line0, colors_line1, colors_line2, colors_line3;
    public JScrollPane leftScroller;
    JScrollPane scrollLocSelector;
    private JSplitPane spliter;
    private MenuPage menuPage;
    private Slider menuPageSlider;
    private boolean editable = false, modifyButtonAvailable = true;// 滑动分割线时为false
    private ArrayList<Record> ar = new ArrayList<>();
    private int operate_sign = 0;
    private Font textFont = new Font(Constant.boldfaceName, Font.BOLD, presentFontSize);
    public  int recordDivideLoc = (int) (FWidth * 0.8);
    private int presentDivideLoc = recordDivideLoc;
    public Handler handler;
    public ViewControl view;
    public ArrayList<Attr> pointed_attrs = new ArrayList<>();
    public AttrOption attrOptions[];
    public String attrsName[];

    // TextPane using
    private String selected_str;
    private AbstractBorder defaultBorder = new MatteBorder(0,0,0,2, Color.DARK_GRAY);

    public Main() {
        main = this;
        // 设置分隔符的颜色
        try {
            // 在此处必须先指定样式
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            e.printStackTrace();
        }
        UIDefaults uidefs = UIManager.getLookAndFeelDefaults();
        uidefs.put("SplitPane.background", new ColorUIResource(Color.DARK_GRAY));

        initialData();
        assigningTasks();
    }

    public void initialData() {
        presentPage = 0;
        recordPage = 0;
        recordCarePosition = 0;
    }
    /**
     * 任务分配
     */
    private void assigningTasks() {
        Singleton.cfgOperator().readConfiguration(); // #1 创建或读取配置文件
        attrOptions = new AttrOption[pointed_attrs.size()]; // #2 设置属性from #1

        handler = Handler.getHandler(); // #3 建立事务处理员
        uiSet(); // #4 UI界面设置 use #2 #3
        handler.SetUp(); // #5 当全部必要组件添加完之后，开始处理一些事务 use #3

        setSize(); // #6 设置字体大小 from #1，use#4
    }
    /**
     * 界面UI设置 $1
     */
    private void uiSet() {
        setBounds((Constant.screenSize.width - FWidth) / 2, (Constant.screenSize.height - FHeight) / 2, FWidth, FHeight);// 设置位置及大小
        setLayout(null);
        setUndecorated(true);

        // 设置形状
        RoundRectangle2D roundRectangle2d = new RoundRectangle2D.Double(0, 0, FWidth, FHeight, 20, 20); // 圆角
//		Ellipse2D ellipse2d=new Ellipse2D.Double(0, 0, FWidth, FHeight); // 椭圆
//		Arc2D arc2d=new Arc2D.Double(0, 0, FWidth, FHeight, 0, 360, Arc2D.PIE);
        setShape(roundRectangle2d);

        layeredPane = new JLayeredPane();
        layeredPane.setLocation(0, 0);
        layeredPane.setSize(FWidth, FHeight);
        layeredPane.setLayout(null);
        add(layeredPane);
        // 最底层0 包含头部和文本部
        ui = new JPanel();
        ui.setBounds(layeredPane.getBounds());
        ui.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        layeredPane.add(ui);
        layeredPane.setLayer(ui, 0);
        // 中间层，划出菜单1
        // 右划，文本操作菜单
        textOpsMenu = new JPanel();
        textOpsMenu.setOpaque(false);
        textOpsMenu.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        textOpsMenu.setBounds(-FWidth, FHeight - 96, FWidth, 66);
        layeredPane.add(textOpsMenu);
        layeredPane.setLayer(textOpsMenu, 1);
        // 左划，属性操作菜单
        meanOpsMenu = new JPanel();
        meanOpsMenu.setOpaque(false);
        meanOpsMenu.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
        meanOpsMenu.setBounds(FWidth, FHeight - 96, FWidth, 66);
        layeredPane.add(meanOpsMenu);
        layeredPane.setLayer(meanOpsMenu, 1);
        // 右划，意象和位置选择版
        locSelector = new JPanel();
        locSelector.setPreferredSize(new Dimension(FWidth, 300));
        locSelector.setBackground(new Color(220, 220, 220));
        locSelector.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        scrollLocSelector = new JScrollPane(locSelector);
        scrollLocSelector.setBounds(-FWidth, FHeight - 180, FWidth, 150);
        layeredPane.add(scrollLocSelector);
        layeredPane.setLayer(scrollLocSelector, 1);
        // 右划，属性显示板
        attrSetter = new JPanel();
        attrSetter.setBounds(-FWidth, recordAttrShowerLoc, FWidth, 196);
        attrSetter.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        attrSetter.setOpaque(false);
        // 确定-撤销版，占领版，常用属性版，九大属性设置版
        // 占领版用来“占领”确定-撤销版的位置，这两个版同时只能有一个可视
        confirmer = new JPanel();
        occupier = new JPanel();
        normalAttr = new JPanel();
        JPanel attrOptions = new JPanel(), attrOptions2 = new JPanel();
        occupier.setOpaque(false);
        occupier.setPreferredSize(new Dimension(FWidth, 32));
        attrSetter.add(occupier);
        colors_line0 = new LineAZer(FWidth, 1, LineAZer.Horizontal);// 彩带
        colors_line0.draw(Color.RED, Color.orange, Color.YELLOW, Color.GREEN, Color.blue, Color.cyan, Color.magenta);
        attrSetter.add(colors_line0);// +
        confirmer.setPreferredSize(new Dimension(FWidth, 32));
        confirmer.setLayout(new GridLayout(1, 2));
        confirmer.add(new MButton(false, this));
        confirmer.add(new MButton(true, this));
        confirmer.setVisible(false);
        attrSetter.add(confirmer);// +
        colors_line1 = new LineAZer(FWidth, 1, LineAZer.Horizontal);// 彩带
        colors_line1.draw(Color.orange, Color.black, new Color(0, 127, 255));
        attrSetter.add(colors_line1);// +
        normalAttr.setLayout(new GridLayout(1, 12));
        normalAttr.setPreferredSize(new Dimension(FWidth, 32));
        normalAttr.setBackground(new Color(220, 225, 255));
        attrOptions.setLayout(new GridLayout(1, 7));
        attrOptions.setPreferredSize(new Dimension(FWidth, 64));
        attrOptions2.setPreferredSize(new Dimension(FWidth, 64));
        attrOptions2.setLayout(new GridLayout(1, 7));
        Iterator<Attr> ia = pointed_attrs.iterator();
        int i = 0;// 0始类型
        while (ia.hasNext()) {
            AttrOption option = new AttrOption(ia.next(), i, normalAttr);
            if (i > 6)
                attrOptions2.add(option);
            else
                attrOptions.add(option);
            this.attrOptions[i++] = option;
        }
        attrSetter.add(attrOptions);// +
        attrSetter.add(attrOptions2);// +
        colors_line2 = new LineAZer(FWidth, 1, LineAZer.Horizontal);// 彩带
        colors_line2.draw(Color.yellow, Color.LIGHT_GRAY, Color.cyan);
        attrSetter.add(colors_line2);// +
        attrSetter.add(normalAttr);// +
        colors_line3 = new LineAZer(FWidth, 2, LineAZer.Horizontal);// 彩带
        colors_line3.draw(Color.RED, Color.orange, Color.YELLOW, Color.GREEN, Color.blue, Color.cyan, Color.magenta);
        attrSetter.add(colors_line3);// +
        layeredPane.add(attrSetter);
        layeredPane.setLayer(attrSetter, 1);
        // 上层，菜单页2
        menuPage = MenuPage.getMenuPage();
        layeredPane.add(menuPage);
        layeredPane.setLayer(menuPage, 2);
        // 隐藏层
        hider = new JPanel();
        hider.setBounds(0, 30, FWidth, FHeight - 30);
        hider.setBackground(new Color(0, 0, 0, 100));
        hider.setVisible(false);
        layeredPane.add(hider);
        layeredPane.setLayer(hider, 3);
        menuPageSlider = Slider.d_break(menuPage, Slider.TOP, menuPage.getHeight(), 200, Slider.RETURN, (float) 0.4, (float) 0.2);
//		cs=Slider.d_break(calculation, Slider.TOP, calculation.getHeight(), 200, Slider.RETURN, (float)0.4,(float) 0.2);
        slideJudge();
        setIconImage(pngIcon("project_logo").getImage());

        addTitle(); // 设置头部
        addContent(); // 设置内容
    }

    /**
     * 添加头部 $2
     */
    private void addTitle() {
        title = new JPanel();
        title.setPreferredSize(new Dimension(FWidth, 30));
        title.setBackground(Constant.titleColor);
        Dragger.drag(this, title, new Point(0, 0), new Point(Constant.screenSize.width - 100,
                Constant.screenSize.height - 100));

        ImageIcon i = resource.getIcon("project_logo.gif");
        Image set = i.getImage().getScaledInstance(50, 50, Image.SCALE_DEFAULT);
        i = new ImageIcon(set);
        MLabel icon = new MLabel(i);

        titleConstraints = new GridBagConstraints();
        titleConstraints.gridheight = 1;
        titleConstraints.gridwidth = 1;
        titleConstraints.gridx = 0;
        titleConstraints.gridy = 0;
        titleConstraints.weightx = 5;
        titleConstraints.weighty = 1;
        titleConstraints.fill = GridBagConstraints.BOTH;
        title.add(icon, titleConstraints);

        int x = 1;
        MLabel word = new MLabel(Constant.CN_NAME + " " + Constant.VERSION, false);
        title.setLayout(new GridBagLayout());

        addTitleButton(word, x++, 25);
        x = addTitleButtons(x, bSave, bLastPara);
        addTitleButton(jtfCurrentPage, x++, 20);
        x = addTitleButtons(x, bNextPara, bSizeDown, lPreSize);
        lPreSize.setBackground(Color.DARK_GRAY);
        addTitleButtons(x, bSizeUp, bModifyText, bOpenMenu, bMinimize, bExit);

        bSave.setToolTipText("点击保存");
        bLastPara.setToolTipText("上一段");
        jtfCurrentPage.setToolTipText("当前段号");
        bNextPara.setToolTipText("下一段");
        bSizeUp.setToolTipText("增大字号");
        bSizeDown.setToolTipText("减小字号");
        lPreSize.setToolTipText("当前字号");
        bOpenMenu.setToolTipText("打开/收起 菜单");
        bMinimize.setToolTipText("最小化");
        bExit.setToolTipText("点击后软件不显示提示框直接退出，说明已经保存");
        bModifyText.setToolTipText("选中修改文章");

        bModifyText.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e){// 选中为1取消为2
                if (!handler.editModel && modifyButtonAvailable) {
                    intoModifyMode();
                    bModifyText.setIcon(pngIcon("adjust_done"));
                    bModifyText.setText("完成修改");
                } else if (modifyButtonAvailable) {
                    outModifyMode();
                    bModifyText.setIcon(pngIcon("adjust"));
                    bModifyText.setText("编辑文章");
                }
            }
        });
        bLastPara.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                if (handler.editModel)
                    modifyContextByRecords();
                jtfPrePgPgSet(--presentPage);
                jtfCurrentPage.setBackground(titleColor);
                jtfCurrentPage.setForeground(Color.white);
            }
        });
        bNextPara.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                if (handler.editModel)
                    modifyContextByRecords();
                jtfPrePgPgSet(++presentPage);
                jtfCurrentPage.setBackground(titleColor);
                jtfCurrentPage.setForeground(Color.white);
            }
        });
        jtfCurrentPage.setBorder(null);
        jtfCurrentPage.setFont(new Font(Constant.boldfaceName, Font.BOLD, 18));
        jtfCurrentPage.setBackground(titleColor);
        jtfCurrentPage.setForeground(Color.white);
        jtfCurrentPage.setCaretColor(titleColor);
        jtfCurrentPage.setHorizontalAlignment(JTextField.CENTER);
        jtfCurrentPage.addKeyListener(new KeyAdapter() {
            public void keyTyped(KeyEvent e) {
                int code = e.getKeyChar();
                if (code == 10)
                    jtfPrePgFocusSet(false);
                else if ((code < '0' || code > '9') && code != 8)
                    e.consume();
            }
        });
        jtfCurrentPage.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                jtfPrePgFocusSet(true);
            }
        });
        jtfCurrentPage.addFocusListener(new FocusAdapter() {
            public void focusLost(FocusEvent e) {
                jtfPrePgFocusSet(false);
            }
        });
        bSizeUp.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                upWordSize();
            }
        });
        bSizeDown.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                lowWordSize();
            }
        });
        bOpenMenu.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                slideJudge();
            }
        });
        bExit.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                modifyContextByRecords();

                if (handler.opened() && !handler.saved())
                    new MDialog("还未保存，确认退出？", MDialog.EXIT);
                else {
                    if (handler.editModel) {
                        setSpliterDivideLoc(recordDivideLoc);
//                        cancelTextModify();
                    }
                    exit(true);
                }
            }
        });
        bMinimize.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                setExtendedState(JFrame.ICONIFIED);
            }
        });
        bSave.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                Singleton.fUtil().writeAll();
            }
        });
        bSave.setVisible(false);
        bSave.setBorder(defaultBorder);
        ui.add(title);
    }

    private void addTitleButton(Component component, int gradX, int weightX) {
        titleConstraints.gridx = gradX;
        titleConstraints.weightx = weightX;
        title.add(component, titleConstraints);
    }

    // 顺序添加宽度要求为 5% 的按钮
    private int addTitleButtons(int gradX, Component... components) {
        for (Component c: components) {
            addTitleButton(c, gradX++, 5);
        }
        return gradX;
    }

    /**
     * if User choose not-save, then save nothing except Configuration.cfg
     * @param saveXDoc if to save changes to XDoc and XML
     */
    public void exit(boolean saveXDoc) {
        if (saveXDoc)
            Singleton.fUtil().writeAll();

        // set the boolean recreate_config
        Singleton.cfgOperator().config_recreate = Singleton.cfgOperator().config_recreate || (
                presentFontSize != recordFontSize ||
                        recordDivideLoc != spliter.getDividerLocation() ||
                        attrSetter.getLocation().y != recordAttrShowerLoc);

        // save Configuration.cfg
        Singleton.cfgOperator().reCreateConfiguration();
        System.exit(-1);
    }

    private void intoModifyMode() {
        editModel(true);
        rightPanel.setVisible(false);
        recordDivideLoc = presentDivideLoc = spliter.getDividerLocation();
        new Thread(() -> {
            modifyButtonAvailable = false;
            int mainWidth = main.getWidth();
            while (presentDivideLoc < mainWidth) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                presentDivideLoc += 25;
                spliter.setDividerLocation(presentDivideLoc);
            }
            spliter.setDividerLocation(mainWidth);
            modifyButtonAvailable = true;
        }).start();
    }

    // Param: cancelModify
    private void outModifyMode() {
        editModel(false);
        new Thread(() -> {
            modifyButtonAvailable = false;
            while (presentDivideLoc > recordDivideLoc) {
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                presentDivideLoc -= 25;
                spliter.setDividerLocation(presentDivideLoc);
            }
            spliter.setDividerLocation(recordDivideLoc);
            modifyButtonAvailable = true;
        }).start();
        rightPanel.setVisible(true);
        modifyContextByRecords();
    }

    private void jtfPrePgFocusSet(boolean gained) {
        jtfCurrentPage.setEditable(gained);
        jtfCurrentPage.setBackground(gained ? Color.LIGHT_GRAY : titleColor);
        jtfCurrentPage.setForeground(gained ? Color.black : Color.WHITE);
        if (gained)
            jtfCurrentPage.setText(presentPage + "");

        else {
            try {
                jtfPrePgPgSet(Integer.parseInt(jtfCurrentPage.getText()));
            } catch (Exception ignored) {
            }
        }
    }

    /**
     * 设置段落
     */
    public void jtfPrePgPgSet(int pg) {
        if (handler.getPgs().size() == 0)
            presentPage = 0;
        else {
            if (pg < 0)
                pg = 0;
            else if (pg > handler.getPgs().size() - 1)
                pg = handler.getPgs().size() - 1;
        }
        presentPage = pg;
        if (pg == 0)
            jtfCurrentPage.setText("全文");
        else
            jtfCurrentPage.setText("第 " + pg + " 段");
        handler.setPage(presentPage);

        view.callBackAll();
        textPane.setCaretPosition(0);
    }

    private void editModel(boolean editModel) {
        textPane.setEditable(editModel);
        editable = editModel;
        handler.turnEditModel(editModel);
//		b_implicit.setVisible(!editModel);
        bOpenMenu.setVisible(!editModel);
        if (editModel)
            textModeFader.goOn();
        else
            textModeFader.goBack();
    }

    public void slideDownMeun(boolean yes) {
        operate_sign = yes ? 0 : 1;
        slideJudge();
    }

    public void saveSet() {
        bSave.setText(handler.saved() ? "已保存" : "未保存");
        bSave.setIcon(pngIcon(handler.saved() ? "xdoc_saved" : "xdoc_save"));
    }

    /**
     * 菜单页的滑动判断（状态转换）
     */
    private void slideJudge() {
        if (operate_sign == 1) {
            menuPageSlider.goBack();
            operate_sign = 0;
            bOpenMenu.setText("  ↑");
            top_buttons_visible(true);
            setEnableUnderMenuPage(true);
        } else {
            top_buttons_visible(false);
            menuPage.setEnableOfButtonsOnMainPage();
            menuPageSlider.start();
            operate_sign = 1;
            bOpenMenu.setText("  ↓");
        }
    }

    private void setEnableUnderMenuPage(boolean enable) {
        if (textPane != null && rightPanel != null) {
            textPane.setVisible(enable);
            rightPanel.setVisible(enable);
        }
    }

    private void top_buttons_visible(boolean visible) {
        bModifyText.setVisible(visible);
        bSizeUp.setVisible(visible);
        bSizeDown.setVisible(visible);
        lPreSize.setVisible(visible);
        bOpenMenu.setVisible(visible);
        bLastPara.setVisible(visible);
        jtfCurrentPage.setVisible(visible);
        bNextPara.setVisible(visible);
        bSave.setVisible(visible || handler.opened());
        bOpenMenu.setVisible(visible || handler.opened());
    }

    /**
     * 添加内容版 $3
     */
    private void addContent() {
        LineAZer topLine = new LineAZer(FWidth, 1, LineAZer.Horizontal);
        topLine.draw(new Color(37, 37, 37), new Color(240, 245, 255));
        ui.add(topLine);
        // 分割面板
        spliter = new JSplitPane();
        spliter.setPreferredSize(new Dimension(FWidth, FHeight - 61));
        spliter.setDividerLocation(recordDivideLoc);
        spliter.setDividerSize(2);
        // 左边文字版
        textPane = new JTextPane();
        textPane.setBackground(new Color(240, 245, 255));
        textPane.setEditable(false);
        textPane.setVisible(false);
        textPane.setFont(textFont);
        textPane.setCaretColor(Color.darkGray);

        selected_str = textPane.getSelectedText();
        textPane.addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                if (editable)
                    selected_str = textPane.getSelectedText();
            }
        });

        textPane.addKeyListener(new KeyAdapter() {
            final int backspace = 1, nothing = 0, delete = -1, stop = -10;
            int operation = 0;
            //	String selected;
            boolean ordered = false;

            public void keyTyped(KeyEvent e) {
                if (editable) {
                    if (!ordered)
                        operation = nothing;

                    if (e.isAltDown() || e.isControlDown()) {
                        e.consume();
                        operation = stop;
                    } else if (e.isShiftDown() && e.getKeyChar() == 10)
                        operation = stop;

                    // 选中文本，执行任何操作后，先执行 删除选中文本
                    boolean deletedSelectedText = false;
                    if (operation != stop && selected_str != null) {
                        deletedSelectedText = true;
                        addRecord(handler.getLeftPositionOfSelectedText(), -selected_str.length());
                    }

                    switch (operation) {
                        case delete: // 向右删除，操作不改变光标位置
                            if (e.isShiftDown())
                                break;
                        case backspace: // 向左删除, from = 操作前的光标位置 -1 = 操作后光标位置。删除选中文本后，不再添加记录。
                            if (!deletedSelectedText)
                                addRecord(textPane.getCaretPosition(), -1);
                            break;
                        case nothing: // 有效输入
                            addRecord(textPane.getCaretPosition(), 1);
                        default: // 无效字符
                    }
                    // 如果删除的包含换行符，重置段落
                    selected_str = null;
                    ordered = false;
                }
            }

            public void keyPressed(KeyEvent e) {
                if (e.isControlDown())
                    e.consume();
                if (editable) {
                    switch (e.getKeyCode()) {
                        case 8:
                            operation = backspace;
                            break;
                        case 127:
                            operation = delete;
                            break;
                        default:
                            operation = nothing;
                    }
                    ordered = true;// 中文输入法下部分标点P监听无效，以此判断是否对order赋值
                }
            }
        });
        textModeFader = Fader.fade(textPane, Fader.BACK_GROUND, 200, Fader.RETURN, new Color(255, 224, 122));
        leftScroller = new JScrollPane(textPane);
        spliter.setLeftComponent(leftScroller);
        // 右边属性版
        rightPanel = new JPanel();
        rightPanel.setVisible(false);
        rightPanel.setBackground(new Color(240, 245, 255));
        rightPanel.setPreferredSize(new Dimension(defaultAttrWidth, 100));
        rightPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
        JScrollPane rightScroller = new JScrollPane(rightPanel);
        spliter.setRightComponent(rightScroller);
        ui.add(spliter);
        // 下信息版
        info = new JPanel();
        info.setBackground(new Color(15, 15, 15));
        info.setPreferredSize(new Dimension(FWidth, 30));
        info.setLayout(new FlowLayout(FlowLayout.LEFT, -1, 0));
        LineAZer lg = new LineAZer(814, 30, LineAZer.Horizontal);
        lg.draw(new Color(15, 15, 15), new Color(100, 100, 130), new Color(15, 15, 15));
        Dragger.drag(this, lg);
        info.add(lg);
        ui.add(info);

        // 加载完之后
        bSave.setText("已保存");
    }

    /**
     * 记录文章修改
     */
    private void addRecord(int from, int push) {
        ar.add(new Record(from + (presentPage <= 1 ? 0 : handler.getPgs().get(presentPage - 1)), push));
    }

    /**
     * 根据ar集合修改文章及意象集合
     *
     * from 是变化的开始，push 是变化的位数
     * < from 位的所有意象不考虑修改，[from, from - push] 范围内的删除， > from - push 的向后增加 push 位
     */
    private void modifyContextByRecords() {
        for (Record rec : ar) {
            int from = rec.from();
            int push = rec.push();

            ArrayList<Mean> delete = new ArrayList<>();

            for (Mean next: handler.allMean) {
                int loc = next.getLocation();
                int end = loc + next.getText().length() - 1;

                // 误操作（应该不存在）
                if (push == 0)
                    continue;

                // 输入字段
                if (push > 0) {
                    if (loc >= from) {
                        next.setLocation(loc + push);
                    } else if (end >= from) {
                        delete.add(next);
                        linkParentAndSon(next);
                    }
                    continue;
                }

                // 删除字段
                if (loc > from - push - 1) {
                    next.setLocation(loc + push);
                } else if (end >= from){
                    delete.add(next);
                    linkParentAndSon(next);
                }
            }

            handler.allMean.removeAll(delete);
            handler.mainMean.removeAll(delete);
        }
        // 清空记录并设置修改后对应的变化
        if (ar.size() != 0) {
            ar.clear();
            handler.modified();
            handler.resetContext();
            handler.setPgs();
            view.info_refreshInfo(view.ALL);
            handler.resetAllDescription();
            view.attr_addAll();
        }
    }

    private void linkParentAndSon(Mean mean) {
        if (mean.getLast() != null) {
            mean.getLast().setNext(mean.getNext());
        }
    }


    private void upWordSize() {
        presentFontSize = presentFontSize == MaxSize ? presentFontSize : ++presentFontSize;
        setSize();
    }

    private void lowWordSize() {
        presentFontSize = presentFontSize == MinSize ? presentFontSize : --presentFontSize;
        setSize();
    }

    private void setSize() {
        textPane.setFont(new Font(textPane.getFont().getFamily(), textPane.getFont().getStyle(), presentFontSize));
        lPreSize.setText(presentFontSize + "");
    }

    private ImageIcon pngIcon(String name) {
        return resource.getIcon(name + ".png");
    }

    public static void main(String args[]) {
        Main m = new Main();
        m.setVisible(true);
    }

    public JTextPane getTextPane() {
        return textPane;
    }
    public MenuPage getMenuPage() {
        return menuPage;
    }

    public void setSpliterDivideLocRecord(int location) {
        presentDivideLoc = recordDivideLoc = location;
    }

    public void setSpliterDivideLoc(int location) {
        spliter.setDividerLocation(location);
    }

    public int getSpliterDivideLoc() {
        return Singleton.main().spliter.getDividerLocation();
    }

    public int getShowerLocation() {
        return attrSetter.getLocation().y;
    }
}

/**
 *
 * 头部的几个标签
 */
class MLabel extends JLabel {
    private static final long serialVersionUID = 1L;

    MLabel(String str, boolean center) {
        setTextFont(false);
        setText(str);
        if (center)
            setHorizontalAlignment(JLabel.CENTER);
    }

    MLabel(String str) {
        this(str, true);
    }

    MLabel(ImageIcon icon) {
        super(icon);
        this.setOpaque(true);
        setBackground(Constant.titleColor);
    }

    MLabel(String str, Color aim) {
        this(str, true);
        fade(false, aim);
    }

    MLabel(ImageIcon icon, Color aim) {
        this(icon);
        fade(true, aim);
    }

    MLabel(ImageIcon icon, String text, Color aim) {
        this(icon, aim);
        setTextFont(true);
        setText(text);
    }

    private void setTextFont(boolean bSize) {
        setFont(new Font(Constant.boldfaceName, Font.BOLD, bSize ? 14 : 16));
        setForeground(Color.WHITE);
    }

    private void fade(boolean backGround, Color aim) {
        Fader.fade(this, backGround ? Fader.BACK_GROUND : Fader.FORE_GROUND, 200, Fader.LISTEN_MouseEnter, aim);
    }
}
